<!DOCTYPE html>
<html>
<head>
  <script src="../../processing.js"></script>
  <script src="../init.js"></script>
<link rel="stylesheet" href="../style.css"/></head>
<body><h1><a href="http://ejohn.org/blog/processingjs/">Processing.js</a></h1>
<h2>Molten Bar Chart</h2>

<p>A dynamically-generated bar chart. Move mouse to view dynamic pie chart.</p>

<p><a href="http://ejohn.org/">Molten Bar Chart</a><br>
<script type="application/processing">
int xspacing = 16;   // How far apart should each horizontal location be spaced
int w;              // Width of entire wave
int maxwaves = 4;   // total # of waves to add together
int total = 0;

float theta = 0.0f;
float[] amplitude = new float[maxwaves];   // Height of wave
float[] dx = new float[maxwaves];          // Value for incrementing X, to be calculated as a function of period and xspacing
float[] yvalues;                           // Using an array to store height values for the wave (not entirely necessary)
float[] last;

int pos;
int rel;
int numLines;
int idealLines;
int idealSpacing;
int targetX;

void setup() {
  size(600, 150);
  //frameRate(24);
  colorMode(RGB,255,255,255,100);
  //background(0);
  smooth();
  w = width+16;

  for (int i = 0; i < maxwaves; i++) {
    amplitude[i] = random(20,30);
    float period = random(100,300); // How many pixels before the wave repeats
    dx[i] = (TWO_PI / period) * xspacing;
  }

  last = new float[maxwaves];
  idealLines = numLines = int(w/xspacing);
  idealSpacing = xspacing;
  yvalues = new float[numLines];
}

void draw() {
  pos = constrain(mouseX, 75, width-75);
  rel = 1 - ((pos - 75) / (width - 150));
  
  //background(0);
  fill(0, 10 + ((1 - rel) * 100));
  rect(0, 0, width, height);
  
  //numLines = idealLines + ((1 - rel) * idealLines);
  //xspacing = idealSpacing - (((1 - rel) * idealSpacing) / 2);
  
  calcWave();
  renderWave();
  renderChart();
}

void calcWave() {
  // Increment theta (try different values for 'angular velocity' here
  theta += 0.02;

  // Set all height values to zero
  for (int i = 0; i < numLines; i++) {
    yvalues[i] = 0.0f;
  }
  
  total = 0;
 
  // Accumulate wave height values
  for (int j = 0; j < maxwaves; j++) {
    float x = theta;
    last[j] = 0;
    
    for (int i = 0; i < numLines; i++) {
      // Every other wave is cosine instead of sine
      int diff = j % 2 == 0 ? sin(x) : cos(x);
      int add = diff*amplitude[j];
      
      last[j] += add;
      
      yvalues[i] += add;
      
      total += add;
      
      x+=dx[j]; // - (((1 - rel) * dx[j]) / 2);
    }
  }
}

void renderWave() {
  noStroke();
  
  fill(254,60,0, 120 * rel);
  beginShape();
  vertex(0,height);
  for (int x = 0; x < numLines; x++) {
    vertex(x*xspacing,height/2+yvalues[x]+-5);
    vertex((x*xspacing) + 10,height/2+yvalues[x]-5);
  }
  vertex(width,height);
  endShape(CLOSE);
  
  fill(255,0,0, 120 * rel);
  beginShape();
  vertex(0,height);
  for (int x = 0; x < numLines; x++) {
    vertex(x*xspacing,height/2+yvalues[x]);
    vertex((x*xspacing) + 10,height/2+yvalues[x]);
  }
  vertex(width,height);
  endShape(CLOSE);
  
  //fill(255,0,0,255 - ((x/numLines)*200));
  //rect(x*xspacing,height/2+yvalues[x],10,height*2);
  // - ((1-rel) * 4)
  
  for (int x = 0; x < numLines; x++) {
    fill(255,0,0,255 - ((x/numLines)*200));
    rect(x*xspacing,height/2+yvalues[x],10,height*2);
    // - ((1-rel) * 4)
  }
}

void renderChart() {
  int h = 0;
  
  for (int i=0; i<last.length; i++){
    last[i] = Math.abs(last[i]);
    h += last[i];
  }
  
  int lastAng = 0;
  int tmprel = 1 - rel;
  
  for (int i=0; i<last.length; i++){
    int pct = (last[i] / h) * 360;
    stroke(0, 100 * tmprel);
    fill(255, 255/(i+1), 0, 200 * tmprel);
    arc(pos, 75, 225 * tmprel, 225 * tmprel, lastAng, lastAng+radians(pct));
    lastAng += radians(pct);  
  }
}
</script><canvas width="600" height="150"></canvas></p>
<div style="height:0px;width:0px;overflow:hidden;"></div>

<pre>int xspacing = 16;   // How far apart should each horizontal location be spaced
int w;              // Width of entire wave
int maxwaves = 4;   // total # of waves to add together
int total = 0;

float theta = 0.0f;
float[] amplitude = new float[maxwaves];   // Height of wave
float[] dx = new float[maxwaves];          // Value for incrementing X, to be calculated as a function of period and xspacing
float[] yvalues;                           // Using an array to store height values for the wave (not entirely necessary)
float[] last;

int pos;
int rel;
int numLines;
int idealLines;
int idealSpacing;
int targetX;

void setup() {
  size(600, 150);
  //frameRate(24);
  colorMode(RGB,255,255,255,100);
  //background(0);
  smooth();
  w = width+16;

  for (int i = 0; i < maxwaves; i++) {
    amplitude[i] = random(20,30);
    float period = random(100,300); // How many pixels before the wave repeats
    dx[i] = (TWO_PI / period) * xspacing;
  }

  last = new float[maxwaves];
  idealLines = numLines = int(w/xspacing);
  idealSpacing = xspacing;
  yvalues = new float[numLines];
}

void draw() {
  pos = constrain(mouseX, 75, width-75);
  rel = 1 - ((pos - 75) / (width - 150));
  
  //background(0);
  fill(0, 10 + ((1 - rel) * 100));
  rect(0, 0, width, height);
  
  //numLines = idealLines + ((1 - rel) * idealLines);
  //xspacing = idealSpacing - (((1 - rel) * idealSpacing) / 2);
  
  calcWave();
  renderWave();
  renderChart();
}

void calcWave() {
  // Increment theta (try different values for 'angular velocity' here
  theta += 0.02;

  // Set all height values to zero
  for (int i = 0; i < numLines; i++) {
    yvalues[i] = 0.0f;
  }
  
  total = 0;
 
  // Accumulate wave height values
  for (int j = 0; j < maxwaves; j++) {
    float x = theta;
    last[j] = 0;
    
    for (int i = 0; i < numLines; i++) {
      // Every other wave is cosine instead of sine
      int diff = j % 2 == 0 ? sin(x) : cos(x);
      int add = diff*amplitude[j];
      
      last[j] += add;
      
      yvalues[i] += add;
      
      total += add;
      
      x+=dx[j]; // - (((1 - rel) * dx[j]) / 2);
    }
  }
}

void renderWave() {
  noStroke();
  
  fill(254,60,0, 120 * rel);
  beginShape();
  vertex(0,height);
  for (int x = 0; x < numLines; x++) {
    vertex(x*xspacing,height/2+yvalues[x]+-5);
    vertex((x*xspacing) + 10,height/2+yvalues[x]-5);
  }
  vertex(width,height);
  endShape(CLOSE);
  
  fill(255,0,0, 120 * rel);
  beginShape();
  vertex(0,height);
  for (int x = 0; x < numLines; x++) {
    vertex(x*xspacing,height/2+yvalues[x]);
    vertex((x*xspacing) + 10,height/2+yvalues[x]);
  }
  vertex(width,height);
  endShape(CLOSE);
  
  //fill(255,0,0,255 - ((x/numLines)*200));
  //rect(x*xspacing,height/2+yvalues[x],10,height*2);
  // - ((1-rel) * 4)
  
  for (int x = 0; x < numLines; x++) {
    fill(255,0,0,255 - ((x/numLines)*200));
    rect(x*xspacing,height/2+yvalues[x],10,height*2);
    // - ((1-rel) * 4)
  }
}

void renderChart() {
  int h = 0;
  
  for (int i=0; i<last.length; i++){
    last[i] = Math.abs(last[i]);
    h += last[i];
  }
  
  int lastAng = 0;
  int tmprel = 1 - rel;
  
  for (int i=0; i < last.length; i++){
    int pct = (last[i] / h) * 360;
    stroke(0, 100 * tmprel);
    fill(255, 255/(i+1), 0, 200 * tmprel);
    arc(pos, 75, 225 * tmprel, 225 * tmprel, lastAng, lastAng+radians(pct));
    lastAng += radians(pct);  
  }
}</pre>
</body>
</html>
